--- /dev/null
+/*
+ Read and write QuoVadis files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "quovadis.h"
+
+static FILE *file_in;
+static FILE *file_out;
+static const char *out_fname;
+struct pdb *opdb;
+
+static int ct;
+static char* rec_ptr = NULL;
+static char* current_rec = NULL;
+static int rec_index = 0;
+
+static char *dbname = NULL;
+
+static
+arglist_t quovadis_args[] = {
+ {"dbname", &dbname, "Database name"},
+ {0, 0, 0}
+};
+
+static struct qv_icon_mapping mapping[] = {
+ { gt_unknown, QUESTION_ICON },
+ { gt_traditional, HOSPITAL_ICON },
+ { gt_multi, DOCUMENT_ICON },
+ { gt_virtual, CAMERA_ICON },
+ { gt_letterbox, MAILBOX_ICON },
+ { gt_event, MEETING_ICON },
+ { gt_suprise, GIFTSHOP_ICON },
+};
+
+#define num_mappings (sizeof(mapping) / sizeof(struct qv_icon_mapping))
+
+static geocache_type icon_to_wpt(int icon_bitmap) {
+ int i;
+
+ for (i = 0; i < num_mappings; i++) {
+ if (icon_bitmap == mapping[i].bitmap_id) {
+ return mapping[i].gc_type;
+ }
+ }
+ return gt_unknown;
+}
+
+static int wpt_to_icon(geocache_type type) {
+ int i;
+
+ for (i = 0; i < num_mappings; i++) {
+ if (type == mapping[i].gc_type) {
+ return mapping[i].bitmap_id;
+ }
+ }
+ return QUESTION_ICON;
+}
+
+static void
+docopy(char* dest,
+ const char* src,
+ const int size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ dest[i] = src[i];
+ }
+}
+
+static void
+rd_init(const char *fname, const char *args)
+{
+ file_in = fopen(fname, "rb");
+ if (file_in == NULL) {
+ fatal(MYNAME ": Cannot open %s for reading\n", fname);
+ }
+}
+
+static void
+rd_deinit(void)
+{
+ fclose(file_in);
+ if ( dbname ) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+wr_init(const char *fname, const char *args)
+{
+ file_out = fopen(fname, "wb");
+ out_fname = fname;
+ if (file_out == NULL) {
+ fatal(MYNAME ": Cannot open %s for writing\n", fname);
+ }
+}
+
+static void
+wr_deinit(void)
+{
+ fclose(file_out);
+ if ( dbname ) {
+ xfree(dbname);
+ dbname = NULL;
+ }
+}
+
+static void
+data_read(void)
+{
+ struct record *rec;
+ struct pdb *pdb;
+ struct pdb_record *pdb_rec;
+ int i;
+
+ if (NULL == (pdb = pdb_Read(fileno(file_in)))) {
+ fatal(MYNAME ": pdb_Read failed\n");
+ }
+
+ if ((pdb->creator != MYCREATOR) || (pdb->type != MYTYPE)) {
+ fatal(MYNAME ": Not a QuoVadis file.\n");
+ }
+
+ /* Ignore the first record, it contains one zero byte */
+ for(pdb_rec = pdb->rec_index.rec->next; pdb_rec; pdb_rec=pdb_rec->next) {
+ int num_recs = pdb_rec->data_len / sizeof(struct record);
+ for (i = 0; i < num_recs; i++) {
+ waypoint *wpt_tmp;
+
+ wpt_tmp = xcalloc(sizeof(*wpt_tmp),1);
+
+ rec = (struct record *)
+ &(pdb_rec->data[i * sizeof(struct record)]);
+
+ wpt_tmp->position.longitude.degrees =
+ (be_read32(&rec->longitude) / 1000000.0) - 180.0;
+ wpt_tmp->position.latitude.degrees =
+ 90.0 - (be_read32(&rec->latitude) / 1000000.0);
+ wpt_tmp->shortname = xstrdup(rec->name);
+
+ wpt_tmp->gc_data.type =
+ icon_to_wpt(be_read16(&rec->icon_bitmap));
+
+ waypt_add(wpt_tmp);
+ }
+ }
+ free_pdb(pdb);
+}
+
+
+static void
+quovadis_writewpt(waypoint *wpt)
+{
+ struct record *rec;
+ int i;
+
+ if (current_rec == NULL) {
+ char dummy = 0;
+ struct pdb_record *pdb_rec;
+ pdb_rec = new_Record(0, 0, ct++, 1, &dummy);
+ if (pdb_rec == NULL) {
+ fatal(MYNAME ": libpdb couldn't create record\n");
+ }
+ if (pdb_AppendRecord(opdb, pdb_rec)) {
+ fatal(MYNAME ": libpdb couldn't append record\n");
+ }
+
+ current_rec = xcalloc(MAXCHUNKSIZE, 1);
+ rec_index = 0;
+ rec_ptr = current_rec;
+ }
+
+ rec = xcalloc(sizeof(*rec),1);
+
+ be_write32(&rec->longitude, (wpt->position.longitude.degrees +
+ 180.0) * 1000000.0);
+ be_write32(&rec->latitude, (90.0 - wpt->position.latitude.degrees) * 1000000.0);
+ if ( wpt->shortname ) {
+ strncpy(rec->name, wpt->shortname, 32 );
+ rec->name[31] = '\0';
+ }
+ else {
+ rec->name[0] = '\0';
+ }
+ be_write16(&rec->icon_bitmap, wpt_to_icon(wpt->gc_data.type));
+ be_write32(&rec->note_id, 0);
+ rec->name_scale = DEFAULT_NAME_SCALE;
+ rec->icon_scale = DEFAULT_ICON_SCALE;
+ for (i = 0; i < 7; i++) {
+ rec->reserved[i] = 0;
+ }
+
+ docopy(rec_ptr, (const char*)rec, sizeof(*rec));
+ rec_ptr += sizeof(*rec);
+ rec_index += 1;
+ xfree(rec);
+
+ if (rec_index == MAXRECORDS) {
+ fatal(MYNAME ": cannot store more than %d records at this time.\n",
+ MAXRECORDS);
+ }
+}
+
+struct hdr{
+ char *wpt_name;
+ waypoint *wpt;
+};
+
+static
+int
+compare(const void *a, const void *b)
+{
+ const struct hdr *wa = a;
+ const struct hdr *wb = b;
+
+ return strcmp(wa->wpt->shortname, wb->wpt->shortname);
+}
+
+static void
+data_write(void)
+{
+ int i, ct = waypt_count();
+ struct hdr *htable, *bh;
+ queue *elem, *tmp;
+ extern queue waypt_head;
+ waypoint *waypointp;
+
+ if (NULL == (opdb = new_pdb())) {
+ fatal (MYNAME ": new_pdb failed\n");
+ }
+
+ if ( dbname ) {
+ strncpy( opdb->name, dbname, PDB_DBNAMELEN );
+ }
+ else {
+ strncpy(opdb->name, "QuoVadisMarkerDB", PDB_DBNAMELEN);
+ }
+ opdb->name[PDB_DBNAMELEN-1] = 0;
+ opdb->attributes = PDB_ATTR_BACKUP;
+ opdb->ctime = opdb->mtime = time(NULL) + 2082844800U;
+ opdb->type = MYTYPE; /* CWpt */
+ opdb->creator = MYCREATOR; /* cGPS */
+ opdb->version = 1;
+
+ /*
+ * All this is to sort by waypoint names before going to QuoVadis.
+ * Turns out plain old strcmp will do the trick...
+ */
+
+ htable = xmalloc(ct * sizeof(*htable));
+ bh = htable;
+
+ QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
+ waypointp = (waypoint *) elem;
+ bh->wpt = waypointp;
+ bh->wpt_name = waypointp->shortname;
+ bh ++;
+ }
+ qsort(htable, ct, sizeof(*bh), compare);
+
+ for (i=0;i<ct;i++) {
+ quovadis_writewpt(htable[i].wpt);
+ }
+
+ if (rec_index != 0) {
+ struct pdb_record* pdb_rec;
+ pdb_rec = new_Record(0, 0, ct++, rec_index *
+ sizeof(struct record), current_rec);
+
+ if (pdb_rec == NULL) {
+ fatal(MYNAME ": libpdb couldn't create record\n");
+ }
+
+ if (pdb_AppendRecord(opdb, pdb_rec)) {
+ fatal(MYNAME ": libpdb couldn't append record\n");
+ }
+ }
+ xfree(current_rec);
+
+ pdb_Write(opdb, fileno(file_out));
+ xfree(htable);
+}
+
+
+ff_vecs_t quovadis_vecs = {
+ rd_init,
+ wr_init,
+ rd_deinit,
+ wr_deinit,
+ data_read,
+ data_write,
+ quovadis_args
+};
--- /dev/null
+/*
+ Definitions for QuoVadis files.
+
+ Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+#ifndef __quovadis_h__
+#define __quovadis_h__
+
+#include "defs.h"
+#include "coldsync/palm.h"
+#include "coldsync/pdb.h"
+
+#define MYNAME "QuoVadis"
+#define MYTYPE 0x51564D52 /* QVMR */
+#define MYCREATOR 0x51554F56 /* QUOV */
+
+#define MAXCHUNKSIZE 0x10000 /* 64k Chunk max */
+
+struct record {
+ char name[32];
+ pdb_32 longitude; /* Scaled. (degrees + 180.0) * 1e6 */
+ pdb_32 latitude; /* Scaled. (degrees + 90.0) * 1e6 */
+ pdb_16 icon_bitmap; /* Valid range: 0 - 47 */
+ pdb_32 note_id; /* Global ID of note in NotesDB. Not
+ supported yet */
+ char name_scale; /* Map scale to display the
+ name. Valid range 15-26. 15 =>
+ 18.12 miles, 26 => 46 feet */
+ char icon_scale; /* As above. */
+ unsigned char reserved[8];
+};
+
+struct qv_icon_mapping {
+ const geocache_type gc_type;
+ const int bitmap_id;
+};
+
+/* Icon Types */
+#define QUESTION_ICON 0
+#define RESTARAUNT_ICON 1
+#define BAR_ICON 2
+#define HOTEL_ICON 3
+#define PHONE_ICON 4
+#define HOSPITAL_ICON 5
+#define CHURCH_ICON 6
+#define AIRPORT_ICON 7
+#define TRAIN_ICON 8
+#define BUS_ICON 9
+#define CAR_ICON 10
+#define WRENCH_ICON 11
+#define GASOLINE_ICON 12
+#define PARKING_ICON 13
+#define MAIL_ICON 14
+#define MAILBOX_ICON 15
+#define CLOCK_ICON 16
+#define FLAG_ICON 17
+#define LIBRARY_ICON 18
+#define BUILDINGS_ICON 19
+#define RELIGION_ICON 20
+#define DOCUMENT_ICON 21
+#define ANIMAL_ICON 22
+#define CAMERA_ICON 23
+#define MOVIE_ICON 24
+#define MUSIC_ICON 25
+#define MEETING_ICON 26
+#define RESTROOM_ICON 27
+#define FAMILY_ICON 28
+#define TELEVISION_ICON 29
+#define SAILING_ICON 30
+#define GOLF_ICON 31
+#define WORKOUT_ICON 32
+#define CYCLING_ICON 33
+#define JOGGING_ICON 34
+#define CAMPING_ICON 35
+#define WATER_ICON 36
+#define FOREST_ICON 37
+#define GIFTSHOP_ICON 38
+#define BABY_ICON 39
+#define LOVE_ICON 40
+#define CEMETARY_ICON 41
+#define COMPUTER_ICON 42
+#define MONEY_ICON 43
+#define LEFT_ARROW_ICON 44
+#define RIGHT_ARROW_ICON 45
+#define DOWN_ARROW_ICON 46
+#define UP_ARROW_ICON 47
+
+/* Scale Values */
+#define SCALE_18_12MI 15
+#define SCALE_9_06MI 16
+#define SCALE_4_53MI 17
+#define SCALE_2_26MI 18
+#define SCALE_1_13MI 19
+#define SCALE_0_56MI 20
+#define SCALE_0_28MU 21
+#define SCALE_747FT 22
+#define SCALE_373FT 23
+#define SCALE_186FT 24
+#define SCALE_93FT 25
+#define SCALE_46FT 26
+
+#define MAXRECORDS (MAXCHUNKSIZE / sizeof(struct record))
+/*#define MAXRECORDS 100*/
+#define DEFAULT_ICON_BITMAP QUESTION_ICON
+#define DEFAULT_NAME_SCALE SCALE_2_26MI
+#define DEFAULT_ICON_SCALE SCALE_18_12MI
+
+#endif